﻿using System;
using System.Collections.Generic;
using System.Text;

namespace DlrBasic.Parser.Ast
{
    abstract class StatementsVisitor
    {
        public abstract void BasicProgram(BasicProgram program);
        public abstract void InteractiveLine(InteractiveLine line);
        public abstract void Line(Line line);
        public abstract void Statement(Statement statement);
        public abstract void IfThen(If @if);
        public abstract void IfElse(If @if);
        public abstract void IfEnd(If @if);
    }

    class NumberStatementsVisitor : StatementsVisitor
    {
        public Dictionary<Statement, int> Map;
        public SortedDictionary<int, int> LineStarts;
        public Dictionary<Statement, Statement> NextStatement;

        int currentStatementNumber;
        Queue<Statement> lastStatements = new Queue<Statement>();
        Stack<Queue<Statement>> lastStatementsStack = new Stack<Queue<Statement>>();

        public NumberStatementsVisitor()
        {
            currentStatementNumber = 0;
            Map = new Dictionary<Statement, int>();
            LineStarts = new SortedDictionary<int, int>();
            NextStatement = new Dictionary<Statement, Statement>();
        }

        public override void BasicProgram(BasicProgram program)
        {
        }

        public override void InteractiveLine(InteractiveLine line)
        {
            LineStarts.Add(0, 0);
        }

        public override void Line(Line line)
        {
            LineStarts.Add(line.LineNumber, currentStatementNumber);
        }

        public override void Statement(Statement statement)
        {
            while (lastStatements.Count > 0)
            {
                NextStatement[lastStatements.Dequeue()] = statement;
            }

            Map.Add(statement, currentStatementNumber++);

            lastStatements.Enqueue(statement);
        }

        public override void IfThen(If @if)
        {
            lastStatementsStack.Push(lastStatements);
            lastStatements = new Queue<Statement>();
        }

        public override void IfElse(If @if)
        {
            Queue<Statement> elseQueue = lastStatementsStack.Pop();
            lastStatementsStack.Push(lastStatements);
            lastStatements = elseQueue;
        }

        public override void IfEnd(If @if)
        {
            Queue<Statement> endQueue = lastStatementsStack.Pop();
            while (endQueue.Count > 0)
            {
                lastStatements.Enqueue(endQueue.Dequeue());
            }
        }
    }

    class StatementNames : StatementsVisitor
    {
        public List<string> Names = new List<string>();

        public override void BasicProgram(BasicProgram program)
        {
        }

        public override void InteractiveLine(InteractiveLine line)
        {
        }

        public override void Line(Line line)
        {
        }

        public override void Statement(Statement statement)
        {
            Names.Add(statement.GetType().Name);
        }

        public override void IfThen(If @if)
        {
        }

        public override void IfElse(If @if)
        {
        }

        public override void IfEnd(If @if)
        {
        }
    }
}
